CSS Houdiniμ Layout APIμ κ°λ ₯ν κΈ°λ₯μ μ΄ν΄λ³΄μΈμ. μ΄ νμ μ μΈ κΈ°μ λ‘ μ¬μ©μ μ μ λ μ΄μμ μκ³ λ¦¬μ¦μ μμ±νκ³ , μΉ λμμΈ κΈ°λ₯μ ν₯μμν€λ©°, νμ μ μΈ μ¬μ©μ μΈν°νμ΄μ€λ₯Ό ꡬμΆνλ λ°©λ²μ λ°°μ°μΈμ.
CSS Houdini Layout API: 컀μ€ν λ μ΄μμ μκ³ λ¦¬μ¦ κ°λ° μ¬μΈ΅ λΆμ
μΉμ λμμμ΄ μ§ννκ³ μμΌλ©°, μ΄μ ν¨κ» μΉ κ°λ°μλ μ μ λ 볡μ‘νκ³ μκ°μ μΌλ‘ λ§€λ ₯μ μΈ μ¬μ©μ μΈν°νμ΄μ€λ₯Ό λ§λ€μ΄μΌ νλ μꡬμ μ§λ©΄νκ³ μμ΅λλ€. κΈ°μ‘΄ CSS λ μ΄μμ λ°©μμ κ°λ ₯νμ§λ§, μ§μ μΌλ‘ λ νΉνκ³ μ±λ₯μ΄ λ°μ΄λ λμμΈμ ꡬννλ €κ³ ν λ λλ‘λ μ νμ μ΄λΌκ³ λκ»΄μ§ μ μμ΅λλ€. CSS Houdiniμ Layout APIλ μ΄λ¬ν λ¬Έμ μ μ ν΄κ²°νκΈ° μν΄ νμ μ μΈ λ μ΄μμ μκ³ λ¦¬μ¦ κ°λ° μ κ·Ό λ°©μμ μ 곡ν©λλ€.
CSS Houdiniλ 무μμΈκ°?
CSS Houdiniλ CSS λ λλ§ μμ§μ μΌλΆλ₯Ό κ°λ°μμκ² κ³΅κ°νλ λ‘μ° λ 벨 API μΈνΈμ μ΄μΉμ λλ€. μ΄λ₯Ό ν΅ν΄ μΉ νμ΄μ§μ μ€νμΌλ§ λ° λ μ΄μμμ μ λ‘ μμ΄ μ μ΄ν μ μμ΅λλ€. λΈλΌμ°μ μ κΈ°λ³Έ λ λλ§ μμ§μλ§ μμ‘΄νλ λμ , Houdiniλ κ°λ°μκ° μ¬μ©μ μ μ μ½λλ‘ νμ₯ν μ μλλ‘ μ§μν©λλ€. λΈλΌμ°μ μ μ€νμΌλ§ λ° λ λλ§ νλ‘μΈμ€μ λν "νν¬" μΈνΈλΌκ³ μκ°νλ©΄ λ©λλ€.
μ£Όμ Houdini APIλ λ€μκ³Ό κ°μ΅λλ€.
- CSS Parser API: CSSμ μ μ¬ν ꡬ문μ νμ±νκ³ μ¬μ©μ μ μ μμ±μ λ§λ€ μ μμ΅λλ€.
- CSS Properties and Values API: νΉμ μ ν λ° λμμ κ°μ§ μ¬μ©μ μ μ CSS μμ±μ λ±λ‘μ νμ±νν©λλ€.
- Typed OM (Object Model): CSS μμ±μ μ‘μΈμ€νκ³ μ‘°μνλ λ³΄λ€ ν¨μ¨μ μ΄κ³ μ ν μμ μ μΈ λ°©λ²μ μ 곡ν©λλ€.
- Paint API: JavaScript κΈ°λ° λ λλ§μ μ¬μ©νμ¬ μ¬μ©μ μ μ λ°°κ²½ μ΄λ―Έμ§, ν λ리 λ° κΈ°ν μκ°μ ν¨κ³Όλ₯Ό μ μν μ μμ΅λλ€.
- Animation API: CSS μ λλ©μ΄μ λ° μ νμ λν λ μΈλ°ν μ μ΄λ₯Ό μ 곡ν©λλ€.
- Layout API: μ΄ λ¬Έμμ μ΄μ μ΄λ©°, μ¬μ©μ μ μ λ μ΄μμ μκ³ λ¦¬μ¦μ μ μν μ μμ΅λλ€.
- Worklets: λΈλΌμ°μ μ λ λλ§ νμ΄νλΌμΈμμ μ€νλλ κ²½λ JavaScript μ€ν νκ²½μ λλ€. Houdini APIλ Workletsμ ν¬κ² μμ‘΄ν©λλ€.
Layout API μκ°
Layout APIλ CSS Houdiniμμ κ°μ₯ ν₯λ―Έλ‘μ΄ λΆλΆ μ€ νλλΌκ³ ν μ μμ΅λλ€. κ°λ°μλ JavaScriptλ₯Ό μ¬μ©νμ¬ μ체 λ μ΄μμ μκ³ λ¦¬μ¦μ μ μνμ¬ νμ΄μ§μ νΉμ μμμ λν λΈλΌμ°μ μ κΈ°λ³Έ λ μ΄μμ μμ§μ λ체ν μ μμ΅λλ€. μ΄λ₯Ό ν΅ν΄ κΈ°μ‘΄ CSSλ‘λ λΆκ°λ₯νκ±°λ λ§€μ° μ΄λ €μ λ νμ μ μ΄κ³ κ³ λλ‘ μ¬μ©μ μ μλ λ μ΄μμμ λ§λ€ μ μλ κ°λ₯μ±μ΄ μ΄λ¦½λλ€.
μμλ₯Ό λμ νμΌλ‘ μλ μ λ ¬νλ λ μ΄μμ, μ½ν μΈ ν¬κΈ°μ λ°λΌ λμ μ΄ λλΉλ₯Ό κ°λ μμ‘° 그리λ, λλ νΉμ λ°μ΄ν° μκ°νμ λ§μΆ μμ ν μλ‘μ΄ λ μ΄μμμ λ§λ λ€κ³ μμν΄ λ³΄μΈμ. Layout APIλ μ΄λ¬ν μλ리μ€λ₯Ό νμ€λ‘ λ§λλλ€.
Layout APIλ₯Ό μ¬μ©νλ μ΄μ λ 무μμ λκΉ?
Layout APIλ₯Ό μ¬μ©νλ κ²μ κ³ λ €ν΄μΌ νλ λͺ κ°μ§ μ£Όμ μ΄μ λ λ€μκ³Ό κ°μ΅λλ€.
- μ λ‘ μλ λ μ΄μμ μ μ΄: 컨ν μ΄λ λ΄μμ μμκ° λ°°μΉλκ³ ν¬κΈ°κ° μ‘°μ λλ λ°©μμ μλ²½νκ² μ μ΄ν μ μμ΅λλ€.
- μ±λ₯ μ΅μ ν: μ ν리μΌμ΄μ μ νΉμ μꡬ μ¬νμ λ§κ² λ μ΄μμ μκ³ λ¦¬μ¦μ μ‘°μ νμ¬ λ μ΄μμ μ±λ₯μ μ μ¬μ μΌλ‘ ν₯μμν¬ μ μμ΅λλ€. μλ₯Ό λ€μ΄, νΉμ μ½ν μΈ νΉμ±μ νμ©νλ μ΅μ νλ₯Ό ꡬνν μ μμ΅λλ€.
- κ΅μ°¨ λΈλΌμ°μ μΌκ΄μ±: Houdiniλ μ¬μμ μ§μνλ λ€μν λΈλΌμ°μ μμ μΌκ΄λ κ²½νμ μ 곡νλ κ²μ λͺ©νλ‘ ν©λλ€. λΈλΌμ°μ μ§μμ μμ§ μ§ννκ³ μμ§λ§, λ μμ μ μ΄κ³ μμΈ‘ κ°λ₯ν λ μ΄μμ νκ²½μ μ½μν©λλ€.
- μ»΄ν¬λνΈν λ° μ¬μ¬μ©μ±: 볡μ‘ν λ μ΄μμ λ‘μ§μ νλ‘μ νΈ κ°μ μ½κ² 곡μ ν μ μλ μ¬μ¬μ© κ°λ₯ν μ»΄ν¬λνΈλ‘ μΊ‘μνν©λλ€.
- μ€ν λ° νμ : μΉ λμμΈμ κ²½κ³λ₯Ό λνλ©΄μ μλ‘κ³ μλ€λ₯Έ λ μ΄μμ ν¨ν΄μ νμν©λλ€.
Layout API μλ λ°©μ: λ¨κ³λ³ κ°μ΄λ
Layout APIλ₯Ό μ¬μ©νλ λ°λ λͺ κ°μ§ μ£Όμ λ¨κ³κ° μμ΅λλ€.
- Layout Worklet μ μ: μ¬μ©μ μ μ λ μ΄μμ μκ³ λ¦¬μ¦μ ν¬ν¨νλ JavaScript νμΌ("Layout Worklet")μ λ§λλλ€. μ΄ νμΌμ λ³λμ μ€λ λμμ μ€νλλ―λ‘ κΈ°λ³Έ λΈλΌμ°μ μ€λ λλ₯Ό μ°¨λ¨νμ§ μμ΅λλ€.
- Layout Worklet λ±λ‘: `CSS.layoutWorklet.addModule()` λ©μλλ₯Ό μ¬μ©νμ¬ Layout Workletμ λΈλΌμ°μ μ λ±λ‘ν©λλ€. μ΄λ κ² νλ©΄ μ¬μ©μ μ μ λ μ΄μμ μκ³ λ¦¬μ¦μ μ¬μ©ν μ μμμ λΈλΌμ°μ μ μ립λλ€.
- `layout()` ν¨μ ꡬν: Layout Worklet λ΄μμ `layout()` ν¨μλ₯Ό μ μν©λλ€. μ΄ ν¨μλ μ¬μ©μ μ μ λ μ΄μμ μκ³ λ¦¬μ¦μ ν΅μ¬μ λλ€. λ μ΄μμν μμ(μ: μ¬μ© κ°λ₯ν 곡κ°, μ½ν μΈ ν¬κΈ°, μ¬μ©μ μ μ μμ±)μ λν μ 보λ₯Ό μμ νκ³ μμ μμμ μμΉ λ° ν¬κΈ°μ λν μ 보λ₯Ό λ°νν©λλ€.
- μ¬μ©μ μ μ μμ± λ±λ‘(μ ν μ¬ν): `CSS.registerProperty()` λ©μλλ₯Ό μ¬μ©νμ¬ λ μ΄μμ μκ³ λ¦¬μ¦μ΄ μ¬μ©ν μ¬μ©μ μ μ CSS μμ±μ λ±λ‘ν©λλ€. μ΄λ κ² νλ©΄ CSS μ€νμΌμ ν΅ν΄ λ μ΄μμμ λμμ μ μ΄ν μ μμ΅λλ€.
- λ μ΄μμ μ μ©: `layout:` CSS μμ±μ μ¬μ©νμ¬ μ¬μ©μ μ μ λ μ΄μμ μκ³ λ¦¬μ¦μ μμμ μ μ©ν©λλ€. λ±λ‘ μ€μ λ μ΄μμ μκ³ λ¦¬μ¦μ λΆμ¬ν μ΄λ¦μ μ§μ ν©λλ€.
λ¨κ³λ³ μΈλΆ λΆμ
1. Layout Worklet μ μ
Layout Workletμ μ¬μ©μ μ μ λ μ΄μμ μκ³ λ¦¬μ¦μ ν¬ν¨νλ JavaScript νμΌμ λλ€. μ±λ₯μ μ€μν λ³λμ μ€λ λμμ μ€νλ©λλ€. κ°λ¨ν μμ μΈ `spiral-layout.js`λ₯Ό λ§λ€μ΄ λ³΄κ² μ΅λλ€.
```javascript
// spiral-layout.js
registerLayout('spiral-layout', class {
static get inputProperties() { return ['--spiral-turns', '--spiral-growth']; }
async layout(children, edges, constraints, styleMap) {
const turnCount = parseFloat(styleMap.get('--spiral-turns').value) || 5;
const growthFactor = parseFloat(styleMap.get('--spiral-growth').value) || 20;
const childCount = children.length;
const centerX = constraints.inlineSize / 2;
const centerY = constraints.blockSize / 2;
for (let i = 0; i < childCount; i++) {
const child = children[i];
const angle = (i / childCount) * turnCount * 2 * Math.PI;
const radius = growthFactor * i;
const x = centerX + radius * Math.cos(angle) - child.inlineSize / 2;
const y = centerY + radius * Math.sin(angle) - child.blockSize / 2;
child.styleMap.set('top', y + 'px');
child.styleMap.set('left', x + 'px');
}
return { blockSizes: [constraints.blockSize] };
}
});
```
μ€λͺ :
- `registerLayout('spiral-layout', class { ... })`: μ΄ μ€μ λ μ΄μμ μκ³ λ¦¬μ¦μ `spiral-layout`μ΄λΌλ μ΄λ¦μΌλ‘ λ±λ‘ν©λλ€. μ΄ μ΄λ¦μ CSSμμ μ¬μ©ν μ΄λ¦μ λλ€.
- `static get inputProperties() { return ['--spiral-turns', '--spiral-growth']; }`: λ μ΄μμ μκ³ λ¦¬μ¦μ΄ μ¬μ©ν μ¬μ©μ μ μ CSS μμ±μ μ μν©λλ€. μ΄ κ²½μ° `--spiral-turns`λ λμ μ νμ μλ₯Ό μ μ΄νκ³ , `--spiral-growth`λ λμ μ΄ λ°κΉ₯μͺ½μΌλ‘ μΌλ§λ 빨리 μ±μ₯νλμ§λ₯Ό μ μ΄ν©λλ€.
- `async layout(children, edges, constraints, styleMap) { ... }`: μ΄κ²μ λ μ΄μμ μκ³ λ¦¬μ¦μ ν΅μ¬μ
λλ€. λ€μ μΈμλ₯Ό μ¬μ©ν©λλ€.
- `children`: λ μ΄μμν μμμ μμμ λνλ΄λ `LayoutChild` κ°μ²΄μ λ°°μ΄μ λλ€.
- `edges`: μμμ κ°μ₯μ리μ λν μ λ³΄κ° ν¬ν¨λ κ°μ²΄μ λλ€.
- `constraints`: μ¬μ© κ°λ₯ν 곡κ°(μ: `inlineSize` λ° `blockSize`)μ λν μ λ³΄κ° ν¬ν¨λ κ°μ²΄μ λλ€.
- `styleMap`: λ±λ‘ν μ¬μ©μ μ μ μμ±μ ν¬ν¨νμ¬ CSS μμ±μ κ³μ°λ κ°μ μ‘μΈμ€ν μ μλ `StylePropertyMapReadOnly` κ°μ²΄μ λλ€.
- `layout()` ν¨μ λ΄λΆμ μ½λλ λμ μκ³ λ¦¬μ¦μ λ°λΌ κ° μμμ μμΉλ₯Ό κ³μ°ν©λλ€. `turnCount` λ° `growthFactor` μμ±μ μ¬μ©νμ¬ λμ μ λͺ¨μμ μ μ΄ν©λλ€.
- `child.styleMap.set('top', y + 'px'); child.styleMap.set('left', x + 'px');`: κ° μμ μμμ `top` λ° `left` μ€νμΌμ μ€μ νμ¬ λμ λ΄μ ν¨κ³Όμ μΌλ‘ λ°°μΉν©λλ€.
- `return { blockSizes: [constraints.blockSize] };`: μμμ λΈλ‘ ν¬κΈ°κ° ν¬ν¨λ κ°μ²΄λ₯Ό λ°νν©λλ€. μ΄ κ²½μ° μ¬μ© κ°λ₯ν λΈλ‘ ν¬κΈ°λ₯Ό λ°ννμ§λ§ νμν κ²½μ° λ€λ₯Έ λΈλ‘ ν¬κΈ°λ₯Ό κ³μ°νκ³ λ°νν μ μμ΅λλ€.
2. Layout Worklet λ±λ‘
μ¬μ©μ μ μ λ μ΄μμμ μ¬μ©νκΈ° μ μ Layout Workletμ λΈλΌμ°μ μ λ±λ‘ν΄μΌ ν©λλ€. `CSS.layoutWorklet.addModule()` λ©μλλ₯Ό μ¬μ©νμ¬ μ΄ μμ μ μνν μ μμ΅λλ€. μΌλ°μ μΌλ‘ λ³λμ JavaScript νμΌ λλ HTMLμ `